package com.jiubanqingchen.wish.framework.base.controller;

import com.jfinal.aop.Aop;
import com.jfinal.aop.Before;
import com.jfinal.aop.Clear;
import com.jfinal.core.NotAction;
import com.jfinal.kit.Kv;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.jiubanqingchen.wish.framework.annotation.AuthorityKey;
import com.jiubanqingchen.wish.framework.base.service.ModelService;
import com.jiubanqingchen.wish.framework.enums.SystemStatus;
import com.jiubanqingchen.wish.framework.exception.WishException;
import com.jiubanqingchen.wish.framework.exception.WishExceptionKey;
import com.jiubanqingchen.wish.interceptors.AuthorityInterceptor;

import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * @author light_dust
 * @since 2020/12/22 15:21
 */
@SuppressWarnings({"unchecked"})
public class ModelController<T extends ModelService<M>, M extends Model<M>> extends BaseController implements IModelController {

    //private static final Logger logger = LoggerFactory.getLogger(ModelController.class);

    protected T service;

    private Class<M> modelClazz;

    public ModelController() {
        service = Aop.get(((Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]));
    }

    @NotAction
    protected Class<M> getModelClazz() {
        if (modelClazz == null) {
            modelClazz = (Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        }
        return modelClazz;
    }

    @Override
    @Before(Tx.class)
    @AuthorityKey("add")
    public void add() throws Exception {
        renderJson(SystemStatus.INSERT_SUCCESS, service.insert(getModel(), getExtDataToRecord(), getCurrentUser()));
    }

    @Override
    @Before(Tx.class)
    @AuthorityKey("add")
    public void addBatch() throws Exception {
        renderJson(SystemStatus.INSERT_SUCCESS, service.insertBatch(getModelArray(), getExtDataToRecord(), getCurrentUser()));
    }

    @Override
    @Before(Tx.class)
    @AuthorityKey("delete")
    public void delete() throws Exception {
        preJudge();
        renderJson(SystemStatus.DELETE_SUCCESS, service.delete(getModel(), getExtDataToRecord(), getCurrentUser()));
    }

    @Override
    @Before(Tx.class)
    @AuthorityKey("delete")
    public void deleteBatch() throws Exception {
        preJudge();
        renderJson(SystemStatus.DELETE_SUCCESS, service.deleteBatch(getModelArray(), getExtDataToRecord(), getCurrentUser()));
    }

    @Override
    @AuthorityKey("view")
    public void list() throws Exception {
        renderJson(service.findList(getQueryParams()));
    }

    @Override
    @AuthorityKey("view")
    public void id() throws Exception {
        renderJson(service.findById(getPara(), getQueryParams()));
    }

    @Override
    @AuthorityKey("view")
    public void page() throws Exception {
        renderJson(service.findPage(getQueryParams()));
    }

    @Override
    @Before(Tx.class)
    @AuthorityKey("edit")
    public void update() throws Exception {
        renderJson(SystemStatus.UPDATE_SUCCESS, service.update(getModel(), getExtDataToRecord(), getCurrentUser()));
    }

    @Override
    @Before(Tx.class)
    @AuthorityKey("edit")
    public void updateBatch() throws Exception {
        renderJson(SystemStatus.UPDATE_SUCCESS, service.updateBatch(getModelArray(), getExtDataToRecord(), getCurrentUser()));
    }

    @Override
    @AuthorityKey("download")
    public void downloadExcel() throws Exception {
        service.downloadExcel(getResponse(), getRawDataToObject(Kv.class));
        renderNull();
    }

    @Override
    //@AuthorityKey("add") 暂时处理掉 不太友好
    @Clear(AuthorityInterceptor.class)
    public void newModel() throws Exception {
        renderJson(service.newModel(getExtDataToRecord(), getCurrentUser()));
    }


    @NotAction
    protected List<M> getModelArray() {
        return getRawDataToObjectArray(getModelClazz());
    }

    @NotAction
    protected M getModel() {
        return getRawDataToObject(getModelClazz());
    }

    private void preJudge() throws WishException {
        boolean isDemo = PropKit.getBoolean("wish.isDemo", false);
        if (isDemo) throw new WishException(WishExceptionKey.AUTHORITY_DEMO_NOT_ALLOWED_DELETE);
    }
}
